import { isObject } from '@/mxp-ui/mxp-tool/utils/verify';
import { ed25519 } from '@noble/curves/ed25519';

export type _Result = UniApp.RequestSuccessCallbackResult;
export interface _Config extends Omit<UniApp.RequestOptions, 'complete' | 'fail' | 'header' | 'success' | 'url'> {
  /** 基础路径 */
  baseURL?: string;
  /** 请求头 */
  header?: Record<string, unknown>;
  /** 自定义的配置 */
  custom?: {
    [x: string]: unknown;
    /** 成功代码返回的成功代码 ,默认为 200 */
    successCode?: number;
    /** 状态码的 key 默认为 'code' */
    codeKey?: string;
  };
  /** 请求地址（不建议携带参数，即使携带参数也会把参数处理后放到 data 中，然后交由 uni.request 处理）  */
  url?: string;
}

/**
 * 驼峰转中横线
 */
export function camelCase2KebabCase(name: string) {
  return name.replace(/([A-Z])/g, '-$1').toLowerCase();
}

/** 得到 url */
export function getUrl(baseUrl: unknown, url: unknown): string {
  const _baseUrl = String(baseUrl);
  const _url = String(url);
  if (_url.startsWith('http')) {
    return _url;
  } else {
    return `${_baseUrl.replace(/\/$/, '')}/${_url.replace(/^\//, '')}`;
  }
}

/** 得到请求方法 */
export function getMethod(method: unknown): _Config['method'] {
  const list = ['OPTIONS', 'GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT'];
  const _method = String(method).toUpperCase();
  return list.includes(_method) ? (_method as _Config['method']) : 'POST';
}

/**
 * 得到url的参数转化为对象
 */
export function getUrlParams(url: string) {
  const newurl = String(url);
  if (newurl.indexOf('?') >= 0) {
    const params = newurl.split('?')[1] || '';
    const paramList = params.split('&');
    const obj: Record<string, string> = {};
    for (let i = 0, len = paramList.length; i < len; i++) {
      const info = paramList[i]!.split('=');
      obj[info[0]!] = info[1] ? decodeURI(info[1]) : '';
    }
    return obj;
  } else {
    return {};
  }
}

/**
 *
 * 得到自定义的验证
 *
 */
export function getCustomAuthorization(config: _Config, privateKeyStr: string, token: string | undefined): string {
  // json 转换一下排除 undefined等非法值
  const newData: Record<string, unknown> = JSON.parse(
    JSON.stringify({
      'Dsbb-Custom-Mac': config.header?.['Dsbb-Custom-Mac'] || '',
      'Dsbb-Custom-Timestamp': config.header?.['Dsbb-Custom-Timestamp'] || '',
      'Dsbb-Custom-Platform': config.header?.['Dsbb-Custom-Platform'] || '',
      ...(isObject(config.data) ? config.data : {}),
      'Token': token || undefined,
    })
  );

  const keys: string[] = Object.keys(newData).sort();
  let message: string = keys.reduce((previousValue, currentValue) => {
    let value = '';
    if (newData[currentValue] !== null) {
      value = newData[currentValue] && newData[currentValue] instanceof Object ? JSON.stringify(newData[currentValue]) : String(newData[currentValue] ?? '');
    }
    return `${previousValue}______${currentValue}&${value}`;
  }, '');
  message = message.length >= 6 ? message.replace(/^______+/, '').replace(/______+$/, '') : message;

  // 要签名的数据
  const messageUint8 = stringToUint8Array(message);
  const privateKey = new Uint8Array(uni.base64ToArrayBuffer(privateKeyStr));
  const signature = ed25519.sign(messageUint8, privateKey);
  const arrayBuffer = signature.buffer;
  // 使用 wx.arrayBufferToBase64 将 ArrayBuffer 转换为 Base64 字符串
  const signatureBase64 = uni.arrayBufferToBase64(arrayBuffer);
  // 将签名转换为 Base64 格式（可选）
  return signatureBase64;
}

/**
 * 得到网络状态
 */
export function getNetworkType(): Promise<string> {
  return new Promise((resolve) => {
    uni.getNetworkType({
      success(res) {
        resolve(res.networkType);
      },
      fail() {
        resolve('unknown2');
      },
    });
  });
}

/**
 * 将 string 转为 Uint8Array
 */
function stringToUint8Array(str: string): Uint8Array {
  const utf8Arr = [];
  for (let i = 0; i < str.length; i++) {
    const charCode = str.charCodeAt(i);
    if (charCode <= 0x7f) {
      utf8Arr.push(charCode);
    } else if (charCode <= 0x7ff) {
      // eslint-disable-next-line no-bitwise
      utf8Arr.push(0xc0 | (charCode >> 6));
      // eslint-disable-next-line no-bitwise
      utf8Arr.push(0x80 | (charCode & 0x3f));
    } else if (charCode <= 0xffff) {
      // eslint-disable-next-line no-bitwise
      utf8Arr.push(0xe0 | (charCode >> 12));
      // eslint-disable-next-line no-bitwise
      utf8Arr.push(0x80 | ((charCode >> 6) & 0x3f));
      // eslint-disable-next-line no-bitwise
      utf8Arr.push(0x80 | (charCode & 0x3f));
    }
  }
  return new Uint8Array(utf8Arr);
}
